package com.riversoft.weixin.pay.face;

import com.riversoft.weixin.common.WxSslClient;
import com.riversoft.weixin.common.exception.WxRuntimeException;
import com.riversoft.weixin.common.util.JsonMapper;
import com.riversoft.weixin.common.util.RandomStringGenerator;
import com.riversoft.weixin.common.util.XmlObjectMapper;
import com.riversoft.weixin.pay.PayWxClientFactory;
import com.riversoft.weixin.pay.base.PaySetting;
import com.riversoft.weixin.pay.base.WxEndpoint;
import com.riversoft.weixin.pay.face.bean.*;
import com.riversoft.weixin.pay.face.wrapper.*;
import com.riversoft.weixin.pay.payment.wrapper.BaseSettings;
import com.riversoft.weixin.pay.payment.wrapper.OrderQueryRequestWrapper;
import com.riversoft.weixin.pay.payment.wrapper.OrderQueryResponseWrapper;
import com.riversoft.weixin.pay.util.SignatureUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.SortedMap;

/**
 * 刷脸支付
 */
public class FacePays {

    private static Logger logger = LoggerFactory.getLogger(FacePays.class);

    private PaySetting paySetting;

    public void setPaySetting(PaySetting paySetting) {
        this.paySetting = paySetting;
    }

    private WxSslClient wxSslClient;

    public static FacePays defaultPayments() {
        return with(PaySetting.defaultSetting());
    }

    public static FacePays with(PaySetting paySetting) {
        FacePays facePays = new FacePays();
        facePays.setPaySetting(paySetting);
        facePays.setWxSslClient(PayWxClientFactory.getInstance().with(paySetting));
        return facePays;
    }

    public void setWxSslClient(WxSslClient wxSslClient) {
        this.wxSslClient = wxSslClient;
    }

    private void setBaseSettings(BaseSettings wrapper) {
        wrapper.setAppId(paySetting.getAppId());
        wrapper.setMchId(paySetting.getMchId());
    }

    private void sign(BaseSettings wrapper, SortedMap<String, Object> generals) {
        String nonce = RandomStringGenerator.getRandomStringByLength(32);
        generals.put("nonce_str", nonce);
        generals.put("mch_id", paySetting.getMchId());

        wrapper.setNonce(nonce);
        wrapper.setSign(SignatureUtil.sign(generals, paySetting.getKey()));
    }

    /*=========================================刷脸支付开始===============================*/

    /**
     * 获取调用凭证
     * **注：**返回的接口凭证authinfo，可以在expires_in指定的有效期内，同一台机具上重复使用。
     * @param facePayAuthInfoRequest
     * @return
     */
    public FacePayAuthInfoResponse getFacePayAuthInfo(FacePayAuthInfoRequest facePayAuthInfoRequest) {
        FacePayAuthInfoRequestWrapper wrapper=new FacePayAuthInfoRequestWrapper();
        wrapper.setRequest(facePayAuthInfoRequest);
        setBaseSettings(wrapper);
        SortedMap<String, Object> facePayAuthInfoRequestMap = JsonMapper.nonEmptyMapper().getMapper().convertValue(wrapper, SortedMap.class);
        sign(wrapper, facePayAuthInfoRequestMap);

        String url = WxEndpoint.get("url.facepay.payment.wxpayface.authinfo");
        try {
            String xml = XmlObjectMapper.nonEmptyMapper().toXml(wrapper);
            logger.info("支付 FacePayAuthInfo url: ", url);
            logger.info("支付 FacePayAuthInfo request: {}", xml);
            String response = wxSslClient.post(url, xml);
            logger.info("支付 FacePayAuthInfo response: {}", response);

            FacePayAuthInfoResponseWrapper responseWrapper = XmlObjectMapper.defaultMapper().fromXml(response, FacePayAuthInfoResponseWrapper.class);
            return responseWrapper.getResponse();
        } catch (Exception e) {
            throw new WxRuntimeException(999, "pre FacePayAuthInfo failed:" + e.getMessage());
        }
    }

    /**
     * 刷脸支付下单
     * @param facePayOrderRequest
     * @return
     */
    public FacePayOrderResponse facePayOrder(FacePayOrderRequest facePayOrderRequest) {
        FacePayOrderRequestWrapper wrapper=new FacePayOrderRequestWrapper();
        wrapper.setRequest(facePayOrderRequest);
        setBaseSettings(wrapper);
        SortedMap<String, Object> facePayOrderRequestMap = JsonMapper.nonEmptyMapper().getMapper().convertValue(wrapper, SortedMap.class);
        sign(wrapper, facePayOrderRequestMap);

        String url = WxEndpoint.get("url.facepay.payment.order.facepay");
        try {
            String xml = XmlObjectMapper.nonEmptyMapper().toXml(wrapper);
            logger.info("支付 facePayOrder url: ", url);
            logger.info("支付 facePayOrder request: {}", xml);
            String response = wxSslClient.post(url, xml);
            logger.info("支付 facePayOrder response: {}", response);

            FacePayOrderResponseWrapper responseWrapper = XmlObjectMapper.defaultMapper().fromXml(response, FacePayOrderResponseWrapper.class);
            return responseWrapper.getResponse();
        } catch (Exception e) {
            throw new WxRuntimeException(999, "pre order failed:" + e.getMessage());
        }
    }

    /**
     * 查询刷脸支付订单状态
     * @param orderQueryRequest
     * @return
     */
    public com.riversoft.weixin.pay.payment.bean.OrderQueryResponse facePayQuery(com.riversoft.weixin.pay.payment.bean.OrderQueryRequest orderQueryRequest) {
        OrderQueryRequestWrapper wrapper = new OrderQueryRequestWrapper();
        wrapper.setRequest(orderQueryRequest);
        setBaseSettings(wrapper);
        SortedMap<String, Object> queryRequestMap = JsonMapper.nonEmptyMapper().getMapper().convertValue(wrapper, SortedMap.class);
        sign(wrapper, queryRequestMap);

        String url = WxEndpoint.get("url.facepay.payment.order.facepayquery");

        try {
            String xml = XmlObjectMapper.nonEmptyMapper().toXml(wrapper);
            logger.info("支付 query order request: {}", xml);
            String response = wxSslClient.post(url, xml);
            logger.info("支付 query order response: {}", response);

            OrderQueryResponseWrapper responseWrapper = XmlObjectMapper.defaultMapper().fromXml(response, OrderQueryResponseWrapper.class);
            return responseWrapper.getResponse();
        } catch (Exception e) {
            throw new WxRuntimeException(999, "query order failed:" + e.getMessage());
        }

    }







    /*=========================================刷脸支付结束===============================*/


    /*=========================================付款码支付===============================*/

    /**
     * 付款码支付下单
     * @param microPayRequest
     * @return
     */
    public FacePayMicroPayResponse microPayOrder(FacePayMicroPayRequest microPayRequest) {
        FacePayMicroPayRequestWrapper wrapper=new FacePayMicroPayRequestWrapper();
        wrapper.setRequest(microPayRequest);
        setBaseSettings(wrapper);
        SortedMap<String, Object> facePayOrderRequestMap = JsonMapper.nonEmptyMapper().getMapper().convertValue(wrapper, SortedMap.class);
        sign(wrapper, facePayOrderRequestMap);

        String url = WxEndpoint.get("url.facepay.payment.order.micropay");
        try {
            String xml = XmlObjectMapper.nonEmptyMapper().toXml(wrapper);
            logger.info("支付 microPayOrder request: {}", xml);
            String response = wxSslClient.post(url, xml);
            logger.info("支付 microPayOrder response: {}", response);

            FacePayMicroPayResponseWrapper responseWrapper = XmlObjectMapper.defaultMapper().fromXml(response, FacePayMicroPayResponseWrapper.class);
            return responseWrapper.getResponse();
        } catch (Exception e) {
            throw new WxRuntimeException(999, "pre order failed:" + e.getMessage());
        }
    }

    /*=========================================付款码支付===============================*/




}
